//
//  MOEditorViewController.m
//  MOED, Version 1.0
//
//  http://moed.googlecode.com/
//
//  Copyright (c) 2011, Eternity Technologies.
//  All rights reserved.
// 
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright
//      notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//    * Neither the name of the Eternity Technologies nor the
//      names of its contributors may be used to endorse or promote products
//      derived from this software without specific prior written permission.
//
//  THIS SOFTWARE IS PROVIDED BY ETERNITY TECHNOLOGIES ''AS IS'' AND ANY
//  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//  DISCLAIMED. IN NO EVENT SHALL ETERNITY TECHNOLOGIES BE LIABLE FOR ANY
//  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
//  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
//  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

#import "MOEditorViewController.h"

#import "MOFormDescription.h"
#import "MOFormSection.h"
#import "MOFormField.h"
#import "MOFormTableViewDescription.h"

#import "MOEditorTableViewCell.h"

@implementation MOEditorViewController

@synthesize managedObjectContext;
@synthesize managedObject;

@synthesize showCancelButton;
@synthesize deleteOnCancel;
@synthesize isModal;
@synthesize selectFirstRowOnAppear;
@synthesize saveOnDone;
@synthesize isInsert;
@synthesize readOnly;

- (id) initWithFormDescription:(MOFormDescription *) sourceFormDescription {
	self = [super initWithStyle:UITableViewStyleGrouped];
	
	formDescription = [sourceFormDescription retain];
	self.tableView.rowHeight = 50.0;
	self.showCancelButton = NO;
	self.deleteOnCancel = NO;
	self.managedObject = nil;
	self.managedObjectContext = nil;
	self.isModal = NO;
	self.isInsert = YES;
	self.selectFirstRowOnAppear = YES;
	self.readOnly = NO;
	wasCanceled = YES;
	saveOnDone = YES;

	return self;
}


- (void) viewWillAppear:(BOOL)animated {
	
	[super viewWillAppear:animated];
	self.title = formDescription.formName;

	/* UI elements */
	if(!readOnly || isModal) {
		UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone 
																					target:self 
																					action:@selector(saveAndDismissMOEDViewController:)];
		
		self.navigationItem.rightBarButtonItem = doneButton;
		doneButton.enabled = NO;
		[doneButton release];
	}
	
	if(showCancelButton) {
		UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel 
																					  target:self 
																					  action:@selector(discardManagedObject:)];
		self.navigationItem.leftBarButtonItem = cancelButton;
		[cancelButton release];		
	}
	
	/* Add new item if managedObject is nil */
	if(managedObject == nil) {
		managedObject = [[NSEntityDescription insertNewObjectForEntityForName:formDescription.modelName 
													   inManagedObjectContext:self.managedObjectContext] retain];
	}
	
	self.navigationController.toolbarHidden = YES;

	/* Validate this object everytime the view appears */
	[self validateManagedObject];
	
}

- (void) viewDidAppear:(BOOL)animated {
	[super viewDidAppear:animated];
	/* Select the first row in the table */
	if(selectFirstRowOnAppear) {
		NSIndexPath *firstRowIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
		[self.tableView selectRowAtIndexPath:firstRowIndexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
	}
}	

#pragma mark -
#pragma mark Event Handlers

- (void) saveAndDismissMOEDViewController:(id) sender {
	
	if(saveOnDone) {
		NSError *error;
		if(![managedObjectContext save:&error]) {
			
			NSLog(@"[MOEditorViewController/CoreData/ERROR] Couldnt Save %@", [error localizedDescription]);
			
			/* Detail message, http://makingmyapp.blogspot.com/ */
			NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
			if(detailedErrors && [detailedErrors count] > 0) {
				for(NSError* detailedError in detailedErrors) {
					NSLog(@"[MOEditorViewController/CoreData/Detail] %@", [detailedError userInfo]);
				}
			}
			else {
				NSLog(@"[MOEditorViewController/CoreData/UserInfo] %@", [error userInfo]);
			}
		}
	}
	
	self.navigationController.toolbarHidden = NO;
	wasCanceled = NO;
	
	/* Dismiss the view controller depending on modal or not */
	if(isModal) [self dismissModalViewControllerAnimated:YES];
	else[self.navigationController popViewControllerAnimated:YES];
}

- (void) discardManagedObject:(id) sender {
	
	self.navigationController.toolbarHidden = NO;
	wasCanceled = YES;
	
	/* Dismiss the view controller depending on modal or not */
	if(isModal) [self dismissModalViewControllerAnimated:YES];
	else[self.navigationController popViewControllerAnimated:YES];
	
}

#pragma mark -
#pragma mark Memory management

- (void)dealloc {

	/* Not sure if this is a no no, but a logical place to put this for now */
	if(wasCanceled && deleteOnCancel) {
		[self.managedObjectContext deleteObject:self.managedObject];
	}
	
	[managedObject release];
	[formDescription release];
	[managedObjectContext release];
    [super dealloc];

}

#pragma mark -
#pragma mark TableView DataSource

- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView {
	return [formDescription numberOfSections];
}

- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
	return [formDescription numberOfFieldsInSection:section];
}

- (NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
	MOFormSection *formSection = [formDescription formSectionAtIndex:section];
	return formSection.sectionName;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
	NSLog(@"[MOEditorViewController/ERROR] Must Override cellForRowAtIndexPath");
	return nil;
}

- (void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
	
	MOFormField *formFieldInfo = [formDescription formFieldAtIndexPath:indexPath];
	
	MOEditorTableViewCell *formEditorCell = (MOEditorTableViewCell *)cell;
	formEditorCell.selectionStyle = UITableViewCellSelectionStyleNone;
	formEditorCell.textField.delegate = self;
		
	/* Makes the form a display only form */	
	formEditorCell.textField.enabled = YES;
	if(self.readOnly || formFieldInfo.options != nil) {
		formEditorCell.textField.enabled = NO;
		formEditorCell.accessoryType = formFieldInfo.longTextModeInReadOnly ? UITableViewCellAccessoryDisclosureIndicator:UITableViewCellAccessoryNone;
	}
	
	[formEditorCell.textField addTarget:self action:@selector(textFieldValueChanged:) forControlEvents:UIControlEventEditingChanged];
	
	/* Restore value from managed object, Cell has no reference to the managed object */
	if(formFieldInfo.fieldType == MOFieldTypeModel) {
		formEditorCell.textField.text = [[[self.managedObject valueForKey:formFieldInfo.managedObjectKey] valueForKey:formFieldInfo.associationForm.tableViewDescription.titleLabelManagedObjectKey] description];
	}
	else
		formEditorCell.textField.text = [[self.managedObject valueForKey:formFieldInfo.managedObjectKey] description];
}

#pragma mark - TableView Delegate

- (void) tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
	MOEditorTableViewCell *editorCell = (MOEditorTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
	[editorCell.textField resignFirstResponder];
}

#pragma mark -
#pragma mark Textfield Delegate

- (void) textFieldDidBeginEditing:(UITextField *)textField {
	
	MOFormField *fieldInformation = [formDescription formFieldAtTag:textField.tag];
	
	/* Keyboard type on validate */
	if(fieldInformation.fieldType == MOFieldTypeString)
		textField.keyboardType = UIKeyboardTypeAlphabet;
	else if(fieldInformation.fieldType == MOFieldTypeFloat || fieldInformation.fieldType == MOFieldTypeInteger)
		textField.keyboardType = UIKeyboardTypeNumberPad;

	[self.tableView selectRowAtIndexPath:[formDescription indexPathForTag:textField.tag] 
								animated:YES 
						  scrollPosition:UITableViewScrollPositionNone];
	
}

- (void) textFieldDidEndEditing:(UITextField *)textField {
	[textField resignFirstResponder];	
}

-(BOOL) textFieldShouldReturn:(UITextField *)textField {
	[textField resignFirstResponder];
	return YES;
}

/* Use the following handler instead of TextView delegate to record changes */
- (void) textFieldValueChanged:(UITextField *) textField {
	
	MOFormField *fieldInformation = [formDescription formFieldAtTag:textField.tag];
	
	if(fieldInformation.fieldType == MOFieldTypeString)
		[managedObject setValue:textField.text forKey:fieldInformation.managedObjectKey];
	else if(fieldInformation.fieldType == MOFieldTypeInteger)
		[managedObject setValue:[NSNumber numberWithInt:[textField.text integerValue]] forKey:fieldInformation.managedObjectKey];
	else if(fieldInformation.fieldType == MOFieldTypeFloat)
		[managedObject setValue:[NSNumber numberWithFloat:[textField.text floatValue]] forKey:fieldInformation.managedObjectKey];
	
	[self validateManagedObject];
	
}

- (void) validateManagedObject {
	
	NSError *error;
	if(self.isInsert) {
		if([self.managedObject validateForInsert:&error])
			self.navigationItem.rightBarButtonItem.enabled = YES;
		else
			self.navigationItem.rightBarButtonItem.enabled = NO;	
	}
	else {
		if([self.managedObject validateForUpdate:&error])
			self.navigationItem.rightBarButtonItem.enabled = YES;
		else
			self.navigationItem.rightBarButtonItem.enabled = NO;	
	}
	
}

@end

